package com.ruoyi.zhgd.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.zhgd.util.PageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.zhgd.domain.bo.TensionResultBo;
import com.ruoyi.zhgd.domain.vo.TensionResultVo;
import com.ruoyi.zhgd.domain.TensionResult;
import com.ruoyi.zhgd.mapper.TensionResultMapper;
import com.ruoyi.zhgd.service.ITensionResultService;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 张拉结果Service业务层处理
 *
 * @author zyb
 * @date 2023-09-11
 */
@RequiredArgsConstructor
@Service
@DS("sjcj")
public class TensionResultServiceImpl implements ITensionResultService {

    private final TensionResultMapper baseMapper;

    /**
     * 查询张拉结果
     */
    @Override
    public TensionResultVo queryById(String id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询张拉结果列表
     */
    @Override
    public TableDataInfo<TensionResultVo> queryPageList(TensionResultBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<TensionResult> lqw = buildQueryWrapper(bo);
        Page<TensionResultVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询张拉结果列表
     */
    @Override
    public List<TensionResultVo> queryList(TensionResultBo bo) {
        LambdaQueryWrapper<TensionResult> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TensionResult> buildQueryWrapper(TensionResultBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TensionResult> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), TensionResult::getCode, bo.getCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceCode()), TensionResult::getDeviceCode, bo.getDeviceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getHoleNumber()), TensionResult::getHoleNumber, bo.getHoleNumber());
        lqw.eq(bo.getTensioningTime() != null, TensionResult::getTensioningTime, bo.getTensioningTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTensioningSection()), TensionResult::getTensioningSection, bo.getTensioningSection());
        lqw.eq(StringUtils.isNotBlank(bo.getMeasurementPoint()), TensionResult::getMeasurementPoint, bo.getMeasurementPoint());
        lqw.eq(StringUtils.isNotBlank(bo.getInitialStroke()), TensionResult::getInitialStroke, bo.getInitialStroke());
        lqw.eq(StringUtils.isNotBlank(bo.getFirstStroke()), TensionResult::getFirstStroke, bo.getFirstStroke());
        lqw.eq(StringUtils.isNotBlank(bo.getSecondStroke()), TensionResult::getSecondStroke, bo.getSecondStroke());
        lqw.eq(StringUtils.isNotBlank(bo.getThirdStroke()), TensionResult::getThirdStroke, bo.getThirdStroke());
        lqw.eq(StringUtils.isNotBlank(bo.getFourthStroke()), TensionResult::getFourthStroke, bo.getFourthStroke());
        lqw.eq(StringUtils.isNotBlank(bo.getMeasuredConclusion()), TensionResult::getMeasuredConclusion, bo.getMeasuredConclusion());
        lqw.eq(bo.getDesignTension() != null, TensionResult::getDesignTension, bo.getDesignTension());
        lqw.eq(bo.getDesignExtension() != null, TensionResult::getDesignExtension, bo.getDesignExtension());
        lqw.eq(bo.getTotalExtension() != null, TensionResult::getTotalExtension, bo.getTotalExtension());
        lqw.eq(bo.getExtensionError() != null, TensionResult::getExtensionError, bo.getExtensionError());
        lqw.eq(bo.getOverTensionPercentage() != null, TensionResult::getOverTensionPercentage, bo.getOverTensionPercentage());
        lqw.eq(bo.getShrinkageAmount() != null, TensionResult::getShrinkageAmount, bo.getShrinkageAmount());
        lqw.eq(bo.getHoldingTime() != null, TensionResult::getHoldingTime, bo.getHoldingTime());
        lqw.eq(bo.getRecordTime() != null, TensionResult::getRecordTime, bo.getRecordTime());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), TensionResult::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增张拉结果
     */
    @Override
    public Boolean insertByBo(TensionResultBo bo) {
        TensionResult add = BeanUtil.toBean(bo, TensionResult.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改张拉结果
     */
    @Override
    public Boolean updateByBo(TensionResultBo bo) {
        TensionResult update = BeanUtil.toBean(bo, TensionResult.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TensionResult entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除张拉结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public PageUtils ensionResultList(Page page, Map<String, Object> params) {
        baseMapper.ensionResultList(page,params);
        return null;
    }

    @Override
    public List<TensionResultVo> selectCode(Map<String, Object> params) {
        List<TensionResultVo> tensionResultVos = baseMapper.selectCode(params);
        return tensionResultVos;
    }

    /**
     * 张拉报表明细
     *
     * @param params
     * @return
     */
    @Override
    public List<TensionResultVo> reportDetail(Map<String, Object> params) {
        if (ObjectUtils.isEmpty(params.get("stake"))) {
            params.put("stake", "");
        }
        if (ObjectUtils.isEmpty(params.get("beamNo"))) {
            params.put("beamNo", "");
        }
        List<TensionResultVo> vos = baseMapper.reportDetail(params);
        vos = handleHoleNumber(vos);
        List<TensionResultVo> newObjs = new ArrayList<>();
        // 根据linkCode分组
        Map<String, List<TensionResultVo>> linkMap = vos.stream().collect(Collectors.groupingBy(TensionResultVo::getLinkCode));
        for (Map.Entry<String, List<TensionResultVo>> link: linkMap.entrySet()) {
            String linkKey = link.getKey();
            List<TensionResultVo> linkValue = link.getValue();
            // 根据孔号分组
            Map<String, List<TensionResultVo>> holeMaps = linkValue.stream().collect(Collectors.groupingBy(TensionResultVo::getHoleNumber));
            for (Map.Entry<String, List<TensionResultVo>> holeMap: holeMaps.entrySet()) {
                String holeKey = holeMap.getKey();
                List<TensionResultVo> holeValue = holeMap.getValue();
                TensionResultVo newObj = null;

                // 合并一个断面的数据 根据断面分组
                Map<String, List<TensionResultVo>> sectionMap = holeValue.stream().collect(Collectors.groupingBy(TensionResultVo::getTensioningSection));
                for (Map.Entry<String, List<TensionResultVo>> entry: sectionMap.entrySet()) {
                    // 同一断面设置 初始油压 30%油压 100%油压 总伸长值 设计伸长值
                    String key = entry.getKey();
                    List<TensionResultVo> value = entry.getValue();
                    newObj = new TensionResultVo();
                    List<Double> designExtensions = new ArrayList<>();
                    List<Double> totalExtensions = new ArrayList<>();
                    List<Integer> shrinkageAmountList = new ArrayList<>();
                    int mi = 0;
                    boolean xy30 = true;
                    Integer shrinkageAmount = null;
                    for (TensionResultVo vo : value) {
                        String beamType = vo.getBeamType();
                        shrinkageAmount = vo.getShrinkageAmount();
                        if (StringUtils.isNotBlank(beamType)) {
                            int index = beamType.indexOf("米");
                            if (index != -1) {
                                String ss = beamType.substring(0, index);
                                mi = Integer.valueOf(ss);
                                if (mi >= 30) {
                                    xy30 = false;
                                } else {
                                    xy30 = true;
                                }
                            } else {
                                xy30 = true;
                            }
                        } else {
                            xy30 = true;
                        }
                        if (vo.getMeasurementPoint().contains("张拉力")) { // 张拉力
                            if (ObjectUtils.isNotEmpty(vo.getDesignTension())) {
                                BigDecimal tension = new BigDecimal(vo.getDesignTension());
                                BigDecimal res10 = tension.multiply(new BigDecimal(0.1)).setScale(1, BigDecimal.ROUND_HALF_UP);
                                BigDecimal res15 = tension.multiply(new BigDecimal(0.15)).setScale(1, BigDecimal.ROUND_HALF_UP);
                                BigDecimal res30 = tension.multiply(new BigDecimal(0.3)).setScale(1, BigDecimal.ROUND_HALF_UP);
                                BigDecimal res100 = tension.multiply(new BigDecimal(1)).setScale(1, BigDecimal.ROUND_HALF_UP);
                                if (xy30) { // 张拉梁型 < 30 按照10% 计算
                                    newObj.setCszl(res10.toString());
                                } else { // 张拉梁型 >= 30 按照15% 计算
                                    newObj.setCszl(res15.toString());
                                }
                                newObj.setCszl30(res30.toString());
                                newObj.setCszl100(res100.toString());
                            } else {
                                newObj.setCszl(vo.getDesignTension().toString());
                                newObj.setCszl30(vo.getDesignTension().toString());
                                newObj.setCszl100(vo.getDesignTension().toString());
                            }

                        }
                        if (vo.getMeasurementPoint().contains("张拉力")) { // 设计张拉力
                            newObj.setCssjzl(vo.getDesignTension().toString());
                            newObj.setSjzl30(vo.getDesignTension().toString());
                            newObj.setSjzl100(vo.getDesignTension().toString());
                        }
                        if (vo.getMeasurementPoint().contains("油压")) { // 油表读数
                            newObj.setCsyy(vo.getInitialStroke());
                            newObj.setYy30(vo.getFirstStroke());
                            if (ObjectUtils.isEmpty(vo.getFourthStroke())) {
                                newObj.setYy100(vo.getThirdStroke());
                            } else {
                                newObj.setYy100(vo.getFourthStroke());
                            }
                        }
                        if (vo.getMeasurementPoint().contains("伸长量")) { // 伸长值
                            newObj.setCssc(vo.getInitialStroke());
                            newObj.setSc30(vo.getFirstStroke());
                            if (ObjectUtils.isEmpty(vo.getFourthStroke())) {
                                newObj.setSc100(vo.getThirdStroke());
                            } else {
                                newObj.setSc100(vo.getFourthStroke());
                            }
                        }
                        newObj.setId(vo.getId());
                        newObj.setCode(vo.getCode());
                        newObj.setLinkCode(vo.getLinkCode());
                        newObj.setDeviceCode(vo.getDeviceCode());
                        newObj.setHoleNumber(vo.getHoleNumber());
                        newObj.setTensioningSection(vo.getTensioningSection());
                        newObj.setHoleLen(vo.getHoleLen());
                        newObj.setHdsNumber(vo.getHdsNumber());
                        newObj.setShrinkageAmount(vo.getShrinkageAmount());
                        designExtensions.add(vo.getDesignExtension());
                        totalExtensions.add(vo.getTotalExtension());
                        shrinkageAmountList.add(vo.getShrinkageAmount());
                    }
                    newObj.setDesignExtensions(designExtensions);
                    newObj.setTotalExtensions(totalExtensions);
//                    newObj.setShrinkageAmounts(shrinkageAmountList);

                    // 两自由端回缩量及工作段伸长值之和（mm）= 两个断面回缩量之和
//                    shrinkageAmountList.add(shrinkageAmount);
//                    if (shrinkageAmountList.size() == 2) {
//                        Integer shrinkageAmountSum = null;
//                        Integer am1 = shrinkageAmountList.get(0);
//                        Integer am2 = shrinkageAmountList.get(1);
//                        if (am1 != null && am2 != null) {
//                            shrinkageAmountSum = am1 + am2;
//                        } else if (am1 != null && am2 == null){
//                            shrinkageAmountSum = am1;
//                        } else if (am1 == null && am2 != null){
//                            shrinkageAmountSum = am2;
//                        } else {
//                            shrinkageAmountSum = null;
//                        }
//                        newObj.setShrinkageAmountSum(shrinkageAmountSum);
//                    }
                    // 理论伸长值（mm）
                    if (designExtensions.size() > 0) {
                        newObj.setDesignExtension(designExtensions.get(0));
                    }
                    // 设置总伸长值 保留一位小数
                    if (totalExtensions.size() > 0) {
//                        BigDecimal scale = new BigDecimal(totalExtensions.stream().collect(Collectors.summarizingDouble(a -> a)).getSum())
//                            .setScale(1, BigDecimal.ROUND_HALF_UP);
//                        newObj.setTotalExtension(scale.doubleValue());
                        // 由原来计算和改为取第一个值
                        newObj.setTotalExtension(totalExtensions.get(0));
                    }
                    // 设置伸长率 = [(总伸长值1+ 总伸长值2）-设计伸长值*2]/ 设计伸长值*2 同一个孔号的加起来 去掉负号
                    if (totalExtensions.size() > 0 && designExtensions.size() > 0) {
//                        double de = designExtensions.stream().collect(Collectors.summarizingDouble(a -> a)).getSum();
//                        double to = totalExtensions.stream().collect(Collectors.summarizingDouble(a -> a)).getSum();
                        // 由原来计算改为 设置伸长率 = [(总伸长值1）-设计伸长值]/ 设计伸长值 并去掉负号
                        double de = designExtensions.get(0);
                        double to = totalExtensions.get(0);
                        if (de != 0) {
                            double res = (to - de) / de;
                            BigDecimal decimal = new BigDecimal(Math.abs(res) * 100).setScale(1, BigDecimal.ROUND_HALF_UP);// 取绝对值 * 100 向上保留一位小数
                            newObj.setExtensionRate(decimal.doubleValue() + "%");
                        }
                    }
                    newObjs.add(newObj);
                }
            }
        }
        return handleShrinkageAmount(newObjs);
    }

    public List<TensionResultVo> handleHoleNumber(List<TensionResultVo> vos) {
        for (TensionResultVo vo : vos) {
            if (ObjectUtils.isNotEmpty(vo.getHoleNumber()) && vo.getHoleNumber().length() > 4 && vo.getHoleNumber().contains("_")) {
                String s = vo.getHoleNumber().substring(0, 4);
                vo.setHoleNumber(s);
            }
        }
        return vos;
    }

    // 合并同一孔号不同断面回缩量之和
    public List<TensionResultVo> handleShrinkageAmount(List<TensionResultVo> newObjs) {
        Map<String, Integer> summary = newObjs.stream().collect(Collectors.groupingBy(TensionResultVo::getHoleNumber, Collectors.summingInt(TensionResultVo::getShrinkageAmount)));
        Map<String, Integer> val = new HashMap<>();
        for (Map.Entry<String, Integer> entry: summary.entrySet()) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            val.put(key, value);
        }
        newObjs.forEach(item -> {
            for (Map.Entry<String, Integer> entry: val.entrySet()) {
                if (item.getHoleNumber().equals(entry.getKey())) {
                    item.setShrinkageAmountSum(entry.getValue().intValue());
                }
            }
        });
        return newObjs;
    }
}
